package com.parking.order.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.parking.common.core.model.RedisKey;
import com.parking.common.core.model.StateData;
import com.parking.common.core.util.DateUtil;
import com.parking.common.web.util.RedisUtil;
import com.parking.order.dao.EntranceInfoDao;
import com.parking.order.dao.OrderInfoDao;
import com.parking.order.model.EntranceInfo;
import com.parking.order.model.OrderInfo;
import com.parking.order.state.CommonOrderStateChange;
import com.parking.order.util.RegularTimeUtil;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单服务开始结束定时任务类
 * */
@Component
public class OrderStartEndTask {
    /**
     * 订单状态改变方法
     * */
    @Autowired
    private CommonOrderStateChange commonOrderStateChange;
    /**
     * 订单信息数据层
     * */
    @Autowired
    private OrderInfoDao orderInfoDao;
    /**
     * 入场纪录数据层
     * */
    @Autowired
    private EntranceInfoDao entranceInfoDao;
    /**
     * 消息队列转发工具类
     * */
    @Autowired
    private RabbitTemplate rabbitTemplate;
    /**
     * Redis工具类
     * */
    @Autowired
    private RedisUtil redisUtil;
    /**
     * 订单服务开始定时任务
     * 定时时间 与订单开始时间配合 00/15/30/45分钟时执行一次
     * */
    @Transactional
    @XxlJob("orderStart")
    public void orderStart(){
        // now作为参数传入其中

        String time = XxlJobHelper.getJobParam();
        System.out.println("任务参数:"+time);
        System.out.println("====================开始订单定时任务==========================");

        LocalDateTime now = null;
        if(time==null||time.equals("")){
            now = RegularTimeUtil.getStandardTime();
        }else{
            now = DateUtil.stringToLocalDateTime(time,"yyyy-MM-dd HH:mm");
        }

        System.out.println("当前标准时间:"+now);
        List<OrderInfo> orders = orderInfoDao.selectList(new QueryWrapper<OrderInfo>().eq("order_info_state", StateData.ORDER_STATE_IS_PAID).eq("start_time",now));
        System.out.println("===========================已支付的开始时间为当前标准时间的订单信息=========================");
        for (OrderInfo order : orders) {
            System.out.println("订单编号:"+order.getOrderInfoNum()+" 车位信息Id:"+order.getStallInfoId());
        }

        List<OrderInfo> overtimes = orderInfoDao.selectList(new QueryWrapper<OrderInfo>().eq("order_info_state",StateData.ORDER_STATE_SHOULD_END));
        List<Integer> overtimeStallIds = overtimes.stream().map(OrderInfo::getStallInfoId).collect(Collectors.toList());
        System.out.println("===================当前被占的车位信息Id=================================");
        for (Integer overtimeStallId : overtimeStallIds) {
            System.out.print(overtimeStallId);
        }
        System.out.println();

        List<OrderInfo> refundOrders = new ArrayList<>();
        List<OrderInfo> beginOrders = new ArrayList<>();
        for (OrderInfo order : orders) {
            if(overtimeStallIds.contains(order.getStallInfoId())){
                refundOrders.add(order);
            }else beginOrders.add(order);
        }

        System.out.println("========================开始订单=====================");
        for (OrderInfo beginOrder : beginOrders) {
            System.out.print(beginOrder.getOrderInfoNum());
        }
        System.out.println();

        System.out.println("========================退款订单=====================");
        for (OrderInfo refundOrder : refundOrders) {
            System.out.print(refundOrder.getOrderInfoNum());
        }
        System.out.println();

        if(!beginOrders.isEmpty()){
            System.out.println("==================执行订单开始================");

            List<Integer> orderIds = beginOrders.stream().map(OrderInfo::getOrderInfoId).collect(Collectors.toList());

            System.out.println("=========================批量修改订单状态==========================");
            System.out.println("订单修改时间:"+now);
            System.out.println("订单状态:"+StateData.ORDER_STATE_CAN_BEGIN+"(0待支付 1已支付 2可开始 3已开始 4需结束 5已结束 6已取消)");
            orderInfoDao.update(null,new UpdateWrapper<OrderInfo>().in("order_info_id",orderIds).set("order_info_state",StateData.ORDER_STATE_CAN_BEGIN).set("order_update_time",now));

            StringBuilder orderIdsStr = new StringBuilder();
            for (Integer orderId : orderIds) {
                if(!orderIdsStr.toString().equals("")) orderIdsStr.append(",");
                orderIdsStr.append(orderId);
            }
            String orderLogsDescribe = "订单开始时间到 车辆可进场停车";
            Integer logType = StateData.ORDER_LOG_PERSON_TYPE_SYSTEM;
            String logger = "系统自动";
            System.out.println("=========================批量添加订单日志==========================");
            rabbitTemplate.convertAndSend("orderLogBatch",orderIdsStr+","+orderLogsDescribe+","+logType+","+logger);
        }

        if(!refundOrders.isEmpty()){
            System.out.println("==================执行订单退款================");
            // 取消状态 修改时间 自动取消
            System.out.println("=========================批量修改订单状态==========================");
            System.out.println("订单修改时间:"+now);
            System.out.println("订单状态:"+StateData.ORDER_STATE_CANCELED+"(0待支付 1已支付 2可开始 3已开始 4需结束 5已结束 6已取消)");
            System.out.println("是否自动取消:"+StateData.ORDER_STATE_IS_AUTO_CANCEL+"(0非自动取消 1自动取消)");
            orderInfoDao.update(null,new UpdateWrapper<OrderInfo>().in("order_info_id",refundOrders.stream().map(OrderInfo::getOrderInfoId).collect(Collectors.toList())).set("order_update_time",now).set("is_auto_cancel",StateData.ORDER_STATE_IS_AUTO_CANCEL).set("order_info_state",StateData.ORDER_STATE_CANCELED));

            // 添加日志
            StringBuilder orderIdsStr = new StringBuilder();
            for (OrderInfo refundOrder : refundOrders) {
                if(!orderIdsStr.toString().equals("")) orderIdsStr.append(",");
                orderIdsStr.append(refundOrder.getOrderInfoId());
            }
            String orderLogsDescribe = "订单开始时间到 但车位存在车辆超时 自动取消并全额退款";
            Integer logType = StateData.ORDER_LOG_PERSON_TYPE_SYSTEM;
            String logger = "系统自动";
            System.out.println("=========================批量添加订单日志==========================");
            rabbitTemplate.convertAndSend("orderLogBatch",orderIdsStr+","+orderLogsDescribe+","+logType+","+logger);

            // 批量添加退款
            rabbitTemplate.convertAndSend("moneyByDeleteList",orderIdsStr);
        }
    }

    /**
     * 订单服务结束定时任务
     * 定时时间 与订单结束时间配合 00/15/30/45分钟时执行一次
     * */
    @XxlJob("orderEnd")
    @Transactional
    public void orderEnd(){
        String time = XxlJobHelper.getJobParam();
        System.out.println("任务参数:"+time);
        System.out.println("====================结束订单定时任务==========================");

        LocalDateTime now = null;
        if(time==null||time.equals("")){
            now = RegularTimeUtil.getStandardTime();
        }else{
            now = DateUtil.stringToLocalDateTime(time,"yyyy-MM-dd HH:mm");
        }

        List<OrderInfo> ordersNotIn = orderInfoDao.selectList(new QueryWrapper<OrderInfo>().eq("order_info_state", StateData.ORDER_STATE_CAN_BEGIN).eq("end_time",now));
        if(!ordersNotIn.isEmpty()){
            List<Integer> orderIds = ordersNotIn.stream().map(OrderInfo::getOrderInfoId).collect(Collectors.toList());

            orderInfoDao.update(null,new UpdateWrapper<OrderInfo>().in("order_info_id",orderIds).set("order_info_state",StateData.ORDER_STATE_END).set("order_update_time",now));

            StringBuilder orderIdsStr = new StringBuilder();
            for (Integer orderId : orderIds) {
                if(!orderIdsStr.toString().equals("")) orderIdsStr.append(",");
                orderIdsStr.append(orderId);
            }
            String orderLogsDescribe = "订单结束时间到 用户全程未使用该服务";
            Integer logType = StateData.ORDER_LOG_PERSON_TYPE_SYSTEM;
            String logger = "系统自动";
            rabbitTemplate.convertAndSend("orderLogBatch",orderIdsStr+","+orderLogsDescribe+","+logType+","+logger);
        }

        List<OrderInfo> ordersIn = orderInfoDao.selectList(new QueryWrapper<OrderInfo>().eq("order_info_state", StateData.ORDER_STATE_BEGIN).eq("end_time",now));
        if(!ordersIn.isEmpty()){
            // 每个订单 orderIn 对应的stallInfoId 是否存在只进不出的出入场记录
            List<Integer> orderOk = new ArrayList<>();
            List<Integer> orderOvertime = new ArrayList<>();

            List<EntranceInfo> entrances = entranceInfoDao.selectList(new QueryWrapper<EntranceInfo>().in("stall_info_id",ordersIn.stream().map(OrderInfo::getStallInfoId).collect(Collectors.toList())).isNull("entrance_out_time"));
            List<Integer> stallIds = entrances.stream().map(EntranceInfo::getStallInfoId).collect(Collectors.toList());
            for (OrderInfo order : ordersIn) {
                if(stallIds.contains(order.getStallInfoId())) orderOvertime.add(order.getOrderInfoId());
                else orderOk.add(order.getOrderInfoId());
            }

            if(!orderOk.isEmpty()){
                System.out.println("进来了");

                orderInfoDao.update(null,new UpdateWrapper<OrderInfo>().in("order_info_id",orderOk).set("order_info_state",StateData.ORDER_STATE_END).set("order_update_time",now));

                StringBuilder orderIdsStr = new StringBuilder();
                for (Integer orderId : orderOk) {
                    if(!orderIdsStr.toString().equals("")) orderIdsStr.append(",");
                    orderIdsStr.append(orderId);
                }
                String orderLogsDescribe = "订单结束时间到 车辆已经离开车位 订单结束";
                Integer logType = StateData.ORDER_LOG_PERSON_TYPE_SYSTEM;
                String logger = "系统自动";

                System.out.println(orderIdsStr+","+orderLogsDescribe+","+logType+","+logger);
                rabbitTemplate.convertAndSend("orderLogBatch",orderIdsStr+","+orderLogsDescribe+","+logType+","+logger);

            }

            if(!orderOvertime.isEmpty()){

                for (Integer integer : orderOvertime) {
                    System.out.println("订单号:"+integer);
                }
                {
                    System.out.println("修改订单");
                    List<OrderInfo> orders = orderInfoDao.selectList(new QueryWrapper<OrderInfo>().in("order_info_id", orderOvertime));

                    for (OrderInfo order : orders) {
                        System.out.println("修改订单Id"+order.getOrderInfoNum());
                        order.setOrderUpdateTime(now);
                        order.setIsOvertime(StateData.ORDER_IS_OVERTIME_NOT_FINISH);
                        order.setOrderInfoState(StateData.ORDER_STATE_SHOULD_END);
                        orderInfoDao.updateById(order);
                        System.out.println("单次修改订单结束");
                    }
                    //orderInfoDao.update(null,new UpdateWrapper<OrderInfo>().in("order_info_id",orderOvertime).set("order_info_state",StateData.ORDER_STATE_SHOULD_END).set("order_update_time",now).set("is_overtime",StateData.ORDER_IS_OVERTIME_NOT_FINISH));
                    System.out.println("修改订单状态结束");
                }

                StringBuilder orderIdsStr = new StringBuilder();
                for (Integer orderId : orderOvertime) {
                    if(!orderIdsStr.toString().equals("")) orderIdsStr.append(",");
                    orderIdsStr.append(orderId);
                }
                String orderLogsDescribe = "订单结束时间到 但车辆还未离开车位";
                Integer logType = StateData.ORDER_LOG_PERSON_TYPE_SYSTEM;
                String logger = "系统自动";
                {
                    String rabbit = orderIdsStr+","+orderLogsDescribe+","+logType+","+logger;
                    System.out.println("我投消息队列了:"+rabbit);
                    rabbitTemplate.convertAndSend("orderLogBatch",rabbit);
                    System.out.println("我真的投了:"+rabbit);
                }

                System.out.println(1);
                // 新增物业超时订单数
                List<OrderInfo> orders = orderInfoDao.selectList(new QueryWrapper<OrderInfo>().in("order_info_id", orderOvertime));
                System.out.println(2);
                for (OrderInfo order : orders) {
                    if(redisUtil.exist(RedisKey.certifiedOrderOvertime(order.getCertifiedInfoId()))){
                        System.out.println(3);
                        int orderOvertimeNum = Integer.parseInt(redisUtil.get(RedisKey.certifiedOrderOvertime(order.getCertifiedInfoId())));
                        redisUtil.set(RedisKey.certifiedOrderOvertime(order.getCertifiedInfoId()),String.valueOf(orderOvertimeNum+1));
                        System.out.println(orderOvertimeNum);
                    }else{
                        System.out.println(4);
                        redisUtil.set(RedisKey.certifiedOrderOvertime(order.getCertifiedInfoId()),"1");
                    }
                }
                System.out.println(5);
            }
        }
    }
}
